package cn.com.taiji.oospub.wechat.common.tool;


import cn.com.taiji.oospub.wechat.entity.CoursesOrders;
import cn.com.taiji.oospub.wechat.entity.CoursesOrdersDetails;
import cn.com.taiji.oospub.wechat.entity.SchoolBaseInfo;
import cn.com.taiji.oospub.wechat.service.IMemberBaseInfoService;
import cn.com.taiji.oospub.wechat.service.ISchoolBaseInfoService;
import com.github.dreamyoung.mprelation.AutoMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

@Service
public class SmallTicketPrinter {

    @Value("${fei_Url}")
    public String URL;// 不需要修改
    @Value("${fei_User}")
    public String USER;// *必填*：账号名
    @Value("${fei_Ukey}")
    public String UKEY;// *必填*:// 飞鹅云后台注册账号后生成的UKEY
    @Value("${fei_SN}")
    public String SN;// *必填*：打印机编号，必须要在管理后台里添加打印机或调用API接口添加之后，才能调用API
    @Value("${is_printe}")
    private Boolean isPrinte;
    @Autowired
    private AutoMapper autoMapper;
    @Autowired
    private ISchoolBaseInfoService schoolBaseInfoService;
    @Autowired
    private IMemberBaseInfoService memberBaseInfoService;

    // 生成签名字符串
    private static String signature(String USER, String UKEY, String STIME) {
        String s = DigestUtils.shaHex(USER + UKEY + STIME);
        return s;
    }

    public String print(String content) {
        // 标签说明：
        // 单标签:
        // "<BR>"为换行,"<CUT>"为切刀指令(主动切纸,仅限切刀打印机使用才有效果)
        // "<LOGO>"为打印LOGO指令(前提是预先在机器内置LOGO图片),"<PLUGIN>"为钱箱或者外置音响指令
        // 成对标签：
        // "<CB></CB>"为居中放大一倍,"<B></B>"为放大一倍,"<C></C>"为居中,<L></L>字体变高一倍
        // <W></W>字体变宽一倍,"<QR></QR>"为二维码,"<BOLD></BOLD>"为字体加粗,"<RIGHT></RIGHT>"为右对齐
        // 拼凑订单内容时可参考如下格式
        // 根据打印纸张的宽度，自行调整内容的格式，可参考下面的样例格式

        // 通过POST请求，发送打印信息到服务器
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)// 读取超时
                .setConnectTimeout(30000)// 连接超时
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig).build();
        System.err.println(URL);
        HttpPost post = new HttpPost(URL);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("user", USER));
        String STIME = String.valueOf(System.currentTimeMillis() / 1000);
        nvps.add(new BasicNameValuePair("stime", STIME));
        nvps.add(new BasicNameValuePair("sig", signature(USER, UKEY, STIME)));
        nvps.add(new BasicNameValuePair("apiname", "Open_printMsg"));// 固定值,不需要修改
        nvps.add(new BasicNameValuePair("sn", SN));
        nvps.add(new BasicNameValuePair("content", content));
        nvps.add(new BasicNameValuePair("times", "1"));// 打印联数

        CloseableHttpResponse response = null;
        String result = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            response = httpClient.execute(post);
            int statecode = response.getStatusLine().getStatusCode();
            if (statecode == 200) {
                HttpEntity httpentity = response.getEntity();
                if (httpentity != null) {
                    // 服务器返回的JSON字符串，建议要当做日志记录起来
                    result = EntityUtils.toString(httpentity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                post.abort();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;

    }

    // 后厨小票打印
    public String printOrder(List<CoursesOrdersDetails> coursesOrdersDetailsList, CoursesOrders mainOrders) {
        if (!isPrinte) {
            return "";
        }
        SchoolBaseInfo schoolBaseInfo = schoolBaseInfoService.getById(mainOrders.getSchoolId());
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        int b1 = 14, b2 = 6, b3 = 4, b4 = 6;
        String orderInfo = "<CB>" + schoolBaseInfo.getNameZh() + "</CB><BR>";
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<CB>取餐码：" + mainOrders.getTakeCode() + "</CB><BR>";
//        orderInfo += BarcodeGeneration.getDigitBarCode(mainOrders.getOrderCode().split("-")[1]) + "<BR>";
        orderInfo += "<QR>" + mainOrders.getOrderCode() + "</QR><BR>";
        orderInfo += "<C>" + mainOrders.getOrderCode() + "</C><BR>";
        orderInfo += "下单时间: " + format.format(mainOrders.getCreateTime()) + "<BR>";
        orderInfo += "打印时间：" + format.format(LocalDateTime.now()) + "<BR><BR>";
        orderInfo += "取餐日期：" + mainOrders.getTakeTime().toLocalDate() + "<BR><BR>";
        orderInfo += "名称           单价  数量 金额<BR>";
        orderInfo += "--------------------------------<BR>";
        double totals = 0.0;
        for (CoursesOrdersDetails coursesOrdersDetail : coursesOrdersDetailsList) {
            coursesOrdersDetail = autoMapper.mapperEntity(coursesOrdersDetail);
            String title = coursesOrdersDetail.getCourse().getNameCh();
            String price = Double.toString(coursesOrdersDetail.getPrice());
            String num = Double.toString(coursesOrdersDetail.getQuantity());
            BigDecimal prices = new BigDecimal(price);
            BigDecimal nums = new BigDecimal(num);
            String total = "" + prices.multiply(nums);
            totals += Double.parseDouble(total);
            price = addSpace(price, b2);
            num = addSpace(num, b3);
            total = addSpace(total, b4);
            String otherStr = " " + price + num + " " + total;

            int tl = 0;
            try {
                tl = title.getBytes("GBK").length;
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            int spaceNum = (tl / b1 + 1) * b1 - tl;
            if (tl < b1) {
                for (int k = 0; k < spaceNum; k++) {
                    title += " ";
                }
                title += otherStr;
            } else if (tl == b1) {
                title += otherStr;
            } else {
                List<String> list = null;
                if (isEn(title)) {
                    list = getStrList(title, b1);
                } else {
                    list = getStrList(title, b1 / 2);
                }
                String s0 = titleAddSpace(list.get(0));
                title = s0 + otherStr + "<BR>";// 添加 单价 数量 总额
                String s = "";
                for (int k = 1; k < list.size(); k++) {
                    s += list.get(k);
                }
                try {
                    s = getStringByEnter(b1, s);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                title += s;
            }
            orderInfo += title + "<BR>";
        }
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<CB>合计：  " + new DecimalFormat("#0.00").format(totals) + "</CB><BR>";
        orderInfo += "<CB>优惠：  " + new DecimalFormat("#0.00").format(totals - mainOrders.getAmount()) + "</CB><BR>";
        orderInfo += "<CB>实付：  " + new DecimalFormat("#0.00").format(mainOrders.getAmount()) + "</CB><BR>";
        orderInfo += "--------------------------------<BR>";
        switch (mainOrders.getMealCode()) {
            case "01":
                orderInfo += "餐品类型：早餐<BR>";
                break;
            case "02":
                orderInfo += "餐品类型：午餐<BR>";
                break;
            case "03":
                orderInfo += "餐品类型：晚餐<BR>";
                break;
        }
        if ("1".equals(mainOrders.getTakeMealType())) {
            //食堂
            orderInfo += "取餐方式：食堂就餐<BR>";

        } else {
            mainOrders = autoMapper.mapperEntity(mainOrders);
            if ("2".equals(mainOrders.getTakeMealType())) {
                orderInfo += "取餐方式：取餐柜<BR>";
            } else {
                orderInfo += "取餐方式：外卖<BR>";
            }
            orderInfo += "<B>送餐地址：" + mainOrders.getAddress().getAddress() + "</B><BR>";
        }
        if ("3".equals(mainOrders.getTakeMealType())) {
//            orderInfo += "<B>联系电话：" + mainOrders.getAddress().getTel().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2") + "</B><BR>";
            orderInfo += "<B>联系电话：" + mainOrders.getAddress().getTel() + "</B><BR>";
        } else {
//            orderInfo += "<B>联系电话：" + memberBaseInfoService.getById(mainOrders.getMemberId()).getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2") + "</B><BR>";
            orderInfo += "<B>联系电话：" + memberBaseInfoService.getById(mainOrders.getMemberId()).getMobile() + "</B><BR>";
        }
        orderInfo += "<B>顾客姓名：" + mainOrders.getPayMemberName().substring(0, 1) + mainOrders.getPayMemberName().substring(1).replaceAll(".{1}", "*") + "</B><BR>";
        if (StringUtils.hasText(mainOrders.getRemark())) {
            orderInfo += "--------------------------------<BR>";
            orderInfo += "<B>备注：" + mainOrders.getRemark() + "</B><BR>";
        }
        orderInfo += "--------------------------------<BR>";
        orderInfo += "<CB>" + schoolBaseInfo.getMobile() + "</CB>";
        orderInfo += "<BR><BR><BR><BR><CUT>";
        String print = print(orderInfo);
        return print;
    }

    // 查询打印机状态
    public String queryPrinterStatus(String sn) {

        // 通过POST请求，发送打印信息到服务器
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)// 读取超时
                .setConnectTimeout(30000)// 连接超时
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig).build();

        HttpPost post = new HttpPost(URL);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("user", USER));
        String STIME = String.valueOf(System.currentTimeMillis() / 1000);
        nvps.add(new BasicNameValuePair("stime", STIME));
        nvps.add(new BasicNameValuePair("sig", signature(USER, UKEY, STIME)));
        nvps.add(new BasicNameValuePair("apiname", "Open_queryPrinterStatus"));// 固定值,不需要修改
        nvps.add(new BasicNameValuePair("sn", sn));

        CloseableHttpResponse response = null;
        String result = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            response = httpClient.execute(post);
            int statecode = response.getStatusLine().getStatusCode();
            if (statecode == 200) {
                HttpEntity httpentity = response.getEntity();
                if (httpentity != null) {
                    // 服务器返回
                    result = EntityUtils.toString(httpentity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                post.abort();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;

    }

    // 查询是否打印成功
    private String queryOrderState(String orderid) {

        // 通过POST请求，发送打印信息到服务器
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)// 读取超时
                .setConnectTimeout(30000)// 连接超时
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig).build();

        HttpPost post = new HttpPost(URL);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("user", USER));
        String STIME = String.valueOf(System.currentTimeMillis() / 1000);
        nvps.add(new BasicNameValuePair("stime", STIME));
        nvps.add(new BasicNameValuePair("sig", signature(USER, UKEY, STIME)));
        nvps.add(new BasicNameValuePair("apiname", "Open_queryOrderState"));// 固定值,不需要修改
        nvps.add(new BasicNameValuePair("orderid", orderid));

        CloseableHttpResponse response = null;
        String result = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
            response = httpClient.execute(post);
            int statecode = response.getStatusLine().getStatusCode();
            if (statecode == 200) {
                HttpEntity httpentity = response.getEntity();
                if (httpentity != null) {
                    // 服务器返回
                    result = EntityUtils.toString(httpentity);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                post.abort();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;

    }

    public static String titleAddSpace(String str) {
        int k = 0;
        int b = 14;
        try {
            k = str.getBytes("GBK").length;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < b - k; i++) {
            str += " ";
        }
        return str;
    }

    public static String getStringByEnter(int length, String string)
            throws Exception {
        for (int i = 1; i <= string.length(); i++) {
            if (string.substring(0, i).getBytes("GBK").length > length) {
                return string.substring(0, i - 1) + "<BR>"
                        + getStringByEnter(length, string.substring(i - 1));
            }
        }
        return string;
    }

    public static String addSpace(String str, int size) {
        int len = str.length();
        if (len < size) {
            for (int i = 0; i < size - len; i++) {
                str += " ";
            }
        }
        return str;
    }

    public static Boolean isEn(String str) {
        Boolean b = false;
        try {
            b = str.getBytes("GBK").length == str.length();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return b;
    }

    public static List<String> getStrList(String inputString, int length) {
        int size = inputString.length() / length;
        if (inputString.length() % length != 0) {
            size += 1;
        }
        return getStrList(inputString, length, size);
    }

    public static List<String> getStrList(String inputString, int length,
                                          int size) {
        List<String> list = new ArrayList<String>();
        for (int index = 0; index < size; index++) {
            String childStr = substring(inputString, index * length,
                    (index + 1) * length);
            list.add(childStr);
        }
        return list;
    }

    public static String substring(String str, int f, int t) {
        if (f > str.length()) {
            return null;
        }
        if (t > str.length()) {
            return str.substring(f);
        } else {
            return str.substring(f, t);
        }
    }
}
